package com.jcfk.eam.service.mould;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.core.utils.BeanUtils;
import com.jcfk.common.security.utils.SecurityUtils;
import com.jcfk.common.web.domain.DataPage;
import com.jcfk.common.web.domain.RetResult;
import com.jcfk.eam.dao.mould.MouldGroupRecordDao;
import com.jcfk.eam.domain.dto.main.EamAssetInfoDTO;
import com.jcfk.eam.domain.dto.mould.*;
import com.jcfk.eam.domain.po.mould.MouldGroupDetail;
import com.jcfk.eam.domain.po.mould.MouldGroupRecord;
import com.jcfk.eam.domain.query.mould.MouldGroupRecordQuery;
import com.jcfk.eam.enums.AssetKind;
import com.jcfk.eam.service.main.EamAssetInfoService;
import com.jcfk.eam.util.enums.CodeGeneratorEnu;
import com.jcfk.eam.util.enums.CodeParseEnu;
import com.jcfk.system.api.utils.DictionaryUtils;
import com.jcfk.system.domain.dto.SysDictionaryItemDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static com.jcfk.common.core.utils.BeanUtils.convertList;

/**
 * 模具组合记录
 *
 * @author yrl
 * @email
 * @date 2024-11-11
 */
@Service
public class MouldGroupRecordService extends BaseService<MouldGroupRecordDao, MouldGroupRecord> {


    @Resource
    private DictionaryUtils dictionaryUtils;
    @Autowired
    private MouldGroupDetailService mouldGroupDetailService;

    @Resource
    private MouldBomGroupService mouldBomGroupService;

    @Resource
    private EamAssetInfoService eamAssetInfoService;

    /**
     * ModGroupRecord分页查询
     *
     * @param page  分页设置
     * @param query 查询条件
     * @return 分页查询结果
     */
    public DataPage<MouldGroupRecordDTO> queryByPage(DataPage<MouldGroupRecordDTO> page, MouldGroupRecordQuery query) {
        // 分页查询
        query.setMaterialCode(StrUtil.isNotEmpty(query.getMaterialCode()) ? query.getMaterialCode() + "%" : query.getMaterialCode());
        query.setMaterialName(StrUtil.isNotEmpty(query.getMaterialName()) ? query.getMaterialName() + "%" : query.getMaterialName());
        query.setMouldCode(StrUtil.isNotEmpty(query.getMouldCode()) ? query.getMouldCode() + "%" : query.getMouldCode());
        page = this.baseMapper.queryByPage(page, query);
        return page;
    }

    /**
     * 根据条件获取单表信息列表
     *
     * @param query 查询条件
     * @return List<ModGroupRecordDTO>
     */
    public List<MouldGroupRecordDTO> getList(MouldGroupRecordQuery query) {
        // 查询条件
        QueryWrapper<MouldGroupRecord> qw = new QueryWrapper<>();
        qw.lambda().eq(!StrUtil.isEmpty(query.getMaterialId()), MouldGroupRecord::getMaterialId, query.getMaterialId());
        // 查询数据
        List<MouldGroupRecord> list = super.list(qw);

        return convertList(list, MouldGroupRecordDTO.class);
    }

    /**
     * 获取根据关联id详情表列表
     *
     * @param query 查询条件
     * @return List<ModGroupRecordDTO>
     */
    public List<MouldGroupDetailDTO> getDetails(MouldGroupRecordQuery query) {
        // 查询条件
        QueryWrapper<MouldGroupDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(!StrUtil.isEmpty(query.getId()), MouldGroupDetail::getGroupRecordId, query.getId())
                .eq(MouldGroupDetail::getDeleted, "0")
                .orderByAsc(MouldGroupDetail::getSort)
                .orderByAsc(MouldGroupDetail::getCreateTime);
        // 查询数据
        List<MouldGroupDetail> list = mouldGroupDetailService.list(qw);

        return convertList(list, MouldGroupDetailDTO.class);
    }


    /**
     * 判断ModGroupRecord是已经存在
     *
     * @param dto
     * @return
     */
    public RetResult<String> isValid(MouldGroupRecordDTO dto) {
        QueryWrapper<MouldGroupRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
        queryWrapper.eq("group_code", dto.getGroupCode());
        if (!StringUtils.isEmpty(dto.getId())) queryWrapper.ne("id", dto.getId());
        Integer count = this.count(queryWrapper);

        if (count > 0) return RetResult.fail("模具组合编码已存在");

        QueryWrapper<MouldGroupRecord> uniqueWrapper = new QueryWrapper<>();
        uniqueWrapper.eq("deleted", 0);
        uniqueWrapper.eq("mould_code", dto.getMouldCode());
        uniqueWrapper.eq("bom_code", dto.getBomCode());
        if (!StringUtils.isEmpty(dto.getId())) uniqueWrapper.ne("id", dto.getId());
        Integer uniqueCount = this.count(uniqueWrapper);

        if (uniqueCount > 0) return RetResult.fail("模具在该BOM中已组装");
        return RetResult.ok();
    }

    /**
     * 插入模具组合记录
     *
     * @param dto 插入对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(MouldGroupRecordDTO dto) {

        BiFunction<String, String, String> function = (code, label) -> Optional.ofNullable(dictionaryUtils.getDictionaryItems(code)
                        .stream()
                        .filter(d -> d.getItemLabel().equals(label))
                        .findFirst()
                        .orElse(new SysDictionaryItemDTO())
                        .getItemValue())
                .orElse("1");
        String mouldStatus = function.apply("mouldStatus", "组合");
        String groupStatus = function.apply("groupStatus", "空闲");
        // 保存
        MouldGroupRecord item = new MouldGroupRecord();
        BeanUtils.copyProperties(dto, item);
        this.setDefaultValue(item);

        String groupCode = CodeGeneratorEnu.MOULD_CODE.build();
        item.setGroupCode(groupCode);
        item.setGroupStatus(groupStatus);
        item.setMouldStatus(mouldStatus);
        item.setGroupTime(DateUtil.date());
        item.setAssetKind(AssetKind.MOULD.getValue());
        item.setMouldCode(groupCode);
        super.save(item);

        // 保存明细表
        mouldGroupDetailService.saveBatch(dto.getDetails(), item);
    }


    /**
     * 更新模具组合记录
     *
     * @param dto 更新对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(MouldGroupRecordDTO dto) {

        // 保存
        MouldGroupRecord item = new MouldGroupRecord();
        BeanUtils.copyProperties(dto, item);

        // 默认数据
        this.setDefaultValue(item);

        super.updateById(item);

        // 设置关联主键
        for (MouldGroupDetailDTO detail : dto.getDetails()) {
            detail.setGroupRecordId(item.getId());
        }
        // 保存明细表
        mouldGroupDetailService.saveBatch(dto.getDetails(), item);
    }


    /**
     * 根据批量主键删除模具组合记录(逻辑删除)
     *
     * @param dto
     * @return bool
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean logicDeleteList(MouldGroupRecordDTO dto) {

        MouldGroupRecord item = new MouldGroupRecord();

        this.setDefaultValue(item);
        item.setDeleted("1");

        QueryWrapper<MouldGroupRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", dto.getIds());

        return this.update(item, queryWrapper);
    }

    /**
     * 设置添加默认值
     *
     * @param item 添加对象
     */
    public void setDefaultValue(MouldGroupRecord item) {
        if (StrUtil.isEmpty(item.getCreatedUserId())) {
            item.setCreatedUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
            item.setDeleted("0");
            item.setEnabled("1");
            item.setCreatedUserName(SecurityUtils.getUserName());
        }
        item.setLastUpdatedUserId(SecurityUtils.getUserId());
        item.setLastUpdateTime(new Date());

        item.setLastUpdatedUserName(SecurityUtils.getUserName());
    }


    /**
     * 根据主键获取模具组合记录信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public MouldGroupRecordDTO get(String id) {
        // 查询数据
        return this.baseMapper.queryById(id);
    }


    /**
     * 根据主键获取模具组合记录信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public void deleteItem(String id) {
        MouldGroupRecord item = getById(id);
        this.setDefaultValue(item);
        item.setDeleted("1");

        this.updateById(item);
    }

    public MouldAssemblyTableDto getListByMouldCodeAndBomCode(String mouldCode, String bomCode) {
        MouldBomGroupDTO mouldBomGroupDTO = mouldBomGroupService.queryDetailTreeCopyByNum(bomCode);
        MouldAssemblyTableDto result = new MouldAssemblyTableDto();
        if (mouldBomGroupDTO != null) {
            // 查询已组装的明细
            List<MouldGroupDetailDTO> assemblyDetailList = getAssemblyDetailList(mouldCode, bomCode);
            // <bom的displayCode(_000), 已组装的模具>
            Map<String, String> existMouldCode = new HashMap<>();
            if (CollUtil.isNotEmpty(assemblyDetailList)) {
                existMouldCode = assemblyDetailList.stream()
                        .collect(Collectors.toMap(MouldGroupDetailDTO::getDisplayCode, MouldGroupDetailDTO::getMouldCode));
                result.setId(CollUtil.getFirst(assemblyDetailList).getGroupRecordId());
            }
            // 构建结果
            result.setBomCode(mouldBomGroupDTO.getBomCode());
            result.setMaterialId(mouldBomGroupDTO.getMaterialId());
            result.setMouldCode(mouldCode);
            result.setAssetKind(AssetKind.MOULD.getValue().toString());
            result.setDetails(buildTableData(mouldBomGroupDTO.getDetails(), existMouldCode));
        }
        return result;
    }

    private List<MouldAssemblyTableDto.Detail> buildTableData(List<MouldBomDetailDTO> details, Map<String, String> existMouldCode) {
        return details.stream()
                .map(detail -> {
                    MouldAssemblyTableDto.Detail result = new MouldAssemblyTableDto.Detail();
                    BeanUtils.copyProperties(detail, result);
                    // 如果已组装  将已组装的数据赋值
                    result.setMouldCode(existMouldCode.getOrDefault(detail.getDisplayCode(), null));
                    if (CollUtil.isNotEmpty(detail.getDetails())) {
                        // 递归构建树形结构
                        result.setDetails(buildTableData(detail.getDetails(), existMouldCode));
                    }
                    return result;
                })
                .collect(Collectors.toList());
    }

    /**
     * 查询已组装的记录
     *
     * @param mouldCode 模具编码
     * @param bomCode   BOM编码
     * @return
     */
    public List<MouldGroupDetailDTO> getAssemblyDetailList(String mouldCode, String bomCode) {
        return this.baseMapper.getAssemblyDetailList(mouldCode, bomCode);
    }

    /**
     * 校验扫码模具编码是否可用
     *
     * @param mouldCode     模具编码
     * @param bomCode       bom编码
     * @param scanMouldCode 要进行组装的模具编码
     */
    public void validScanMould(String mouldCode, String bomCode, String scanMouldCode) {
        CodeParseEnu.MOULD_CODE.matcherThrow(scanMouldCode);
        // 判断扫描模具是否已被其他模具组装
        EamAssetInfoDTO info = eamAssetInfoService.getNoPicInfoByCode(scanMouldCode);
        Assert.notNull(info, "模具编码不存在");
        Assert.isTrue(info.getAssetKind() == 4, "扫描的资产不属于模具");
        Assert.isTrue(info.getStorageStatus() == 2, "该模具不在线边库，无法操作");
        MouldGroupRecord mouldGroupRecord = this.getOne(Wrappers.<MouldGroupRecord>lambdaQuery()
                .eq(MouldGroupRecord::getMouldCode, mouldCode)
                .eq(MouldGroupRecord::getBomCode, bomCode)
                .eq(MouldGroupRecord::getDeleted, "0")
                .eq(MouldGroupRecord::getEnabled, "1"));
        LambdaQueryWrapper<MouldGroupDetail> wrapper = Wrappers.<MouldGroupDetail>lambdaQuery()
                .eq(MouldGroupDetail::getMouldCode, scanMouldCode)
                .eq(MouldGroupDetail::getGroupStatus, "1")
                .eq(MouldGroupDetail::getDeleted, "0")
                .eq(MouldGroupDetail::getEnabled, "1");
        if (mouldGroupRecord != null) {
            wrapper.ne(MouldGroupDetail::getGroupRecordId, mouldGroupRecord.getId());
        }
        int count = mouldGroupDetailService.count(wrapper);
        Assert.isTrue(count == 0, "模具编码已被其他模具组装");
    }

    public List<MouldGroupRecord> getListByBomCode(String bomCode) {
        return this.list(Wrappers.<MouldGroupRecord>lambdaQuery()
                .eq(MouldGroupRecord::getBomCode, bomCode));
    }

    public MouldGroupRecordDTO getGroupRecordBySubMould(String mouldCode) {
        MouldGroupDetail groupDetail = Optional.ofNullable(mouldGroupDetailService.getOne(Wrappers.<MouldGroupDetail>lambdaQuery()
                .eq(MouldGroupDetail::getMouldCode, mouldCode)
                .eq(MouldGroupDetail::getGroupStatus, "1")
                .eq(MouldGroupDetail::getDeleted, "0")
                .eq(MouldGroupDetail::getEnabled, "1"))).orElseThrow(() -> new IllegalArgumentException("未查询到绑定数据"));
        MouldGroupRecord groupRecord = this.getById(groupDetail.getGroupRecordId());
        MouldGroupRecordDTO result = new MouldGroupRecordDTO();
        BeanUtils.copyProperties(groupRecord, result);
        return result;
    }


    public MouldGroupRecordDTO getGroupRecordBySubMoulds(String mouldCode) {
        MouldGroupDetail groupDetail = mouldGroupDetailService.getOne(Wrappers.<MouldGroupDetail>lambdaQuery()
                .eq(MouldGroupDetail::getMouldCode, mouldCode)
                .eq(MouldGroupDetail::getGroupStatus, "1")
                .eq(MouldGroupDetail::getDeleted, "0")
                .eq(MouldGroupDetail::getEnabled, "1"));
        if (groupDetail == null) {
            return null;
        }
        MouldGroupRecord groupRecord = this.getById(groupDetail.getGroupRecordId());
        MouldGroupRecordDTO result = new MouldGroupRecordDTO();
        BeanUtils.copyProperties(groupRecord, result);
        return result;
    }

    public void scatter(String id) {
        BiFunction<String, String, String> function = (code, label) -> Optional.ofNullable(dictionaryUtils.getDictionaryItems(code)
                        .stream()
                        .filter(d -> d.getItemLabel().equals(label))
                        .findFirst()
                        .orElse(new SysDictionaryItemDTO())
                        .getItemValue())
                .orElse("2");
        String mouldStatus = function.apply("mouldStatus", "未组");
        MouldGroupRecord item = getById(id);
        this.setDefaultValue(item);
        item.setBreakTime(new Date());
        item.setGroupStatus(mouldStatus);

        this.updateById(item);
        mouldGroupDetailService.scatter(item);
    }
}

